#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 更改窗口标题区分客户端服务器
    this->setWindowTitle("服务器");
    // 1. 构建tcpserver对象
    server = new QTcpServer(this);
    // 2. 关联信号槽
    // 不能先绑定! 绑定在前，关联信号槽在后，中间这一过程
    // 可能会有连接到来

    // newConnection 新连接到来的信号
    connect(server,&QTcpServer::newConnection,this,&Widget::processConnection);

    // readyRead 客户端发送数据到来产生的信号
    // 这个信号并不是在这里关联的，而是当新的连接建立成功后才关联的

    // 3.绑定端口号并监听
    bool ret = server->listen(QHostAddress::Any,8888);
    if(!ret)
    {
        QMessageBox::critical(this,"错误",server->errorString());
        return;
    }
}

// 当一个新连接到来时处理新的连接
void Widget::processConnection()
{
    // 1.获取到对应的客户端
    QTcpSocket* client = server->nextPendingConnection();
    // 将对应客户端的信息显示到ListWidget上
    ui->listWidget->addItem("[" + client->peerAddress().toString() + " : " + QString::number(client->peerPort()) + "] 上线了" );

    // 2. 关联信号槽
    // 每个对应的客户端都要去关联信号槽，当任意客户端发送消息时
    // 都能通过信号来告知，用户已经发送数据了，通过槽函数及时处理
    // a) 关联 readyRead
    // 使用一个成员函数还不好处理 对应的readyRead信号
    // 因为client是局部变量，成员函数是访问不到client的
    // 为了方便我们使用lambda
    connect(client,&QTcpSocket::readyRead,this,[=](){
        // 1. 获取请求
        // 这里的业务只是回显，但真的处理过程是需要将我们读取的数据
        // 放到对应的缓冲区中，根据协议来截取完整的报文！
        // 这里不做过多的处理
        QString req = client->readAll();
        // 2. 处理请求构建响应
        QString resp = process(req);
        // 3. 发送数据
        client->write(resp.toUtf8());
        // 4. 将上述信息记录到ListWidget中
        QString log = "[ " + client->peerAddress().toString() + ":" + QString::number(client->peerPort()) + "]"
                      + "request：" + req + "  response：" + resp;
        ui->listWidget->addItem(log);

    });

    // b) 关联disconnected
    connect(client,&QTcpSocket::disconnected ,this,[=](){
         ui->listWidget->addItem("[" + client->peerAddress().toString() + " : " + QString::number(client->peerPort()) + "] 下线了" );
         // 手动释放 clientSocket. 直接使用 delete 是下策, 使用 deleteLater 更加合适的.
         // delete clientSocket;
         client->deleteLater();
    });

}

QString Widget::process(QString req)
{
    return req;
}




Widget::~Widget()
{
    delete ui;
}





